// ==============================================================================
//
// Software Development Kit v 3.0
// Camera API
//
// Copyright (c) 2008-2009 Gear Pair Games
//
// Copyright and license exceptions noted in source
//
// Description: This Struct(s) unit, .
// legent of text:
// :: - public
// :$ - private
// :# - class of object
// ==============================================================================
unit cameraApi;

interface

uses
  types,
  cls,
  headers,
  math,
  msg,
  structs,
  enums;

const
  // default fov
  fovCamDefault = 75;
  aspectRatioDefault = 800 / 600;

type
  // CCameraFactory
  CCameraFactory = class( ICameraFactory )
  private { std::private }
    fCurrCam : ICamera;
  protected { std::protected }
    // CCameraFactory::getCurrCam
    function getCurrCam : ICamera; override;
    // CCameraFactory::setCurrCam
    procedure setCurrCam( const inCam : ICamera ); override;
  public { std::public }
    // CCameraFactory::doInit
    procedure doInit; override;
    // CCameraFactory::doFree
    procedure doFree; override;
  end;

  // CSimpleCamera
  CSimpleCamera = class( ICamera )
  private { std::protected }
    fFov : float;
    fPosCurr, fPosNecessary : vec3;
    fQuatCurr, fQuatNecessary : quat;
    fState : enumOfCamState;
    fMatrix : array [ enumCamMat ] of mat4;
  protected { std::protected }
    // ICamera::getPos
    function getPos : vec3; override;
    // ICamera::setPos
    procedure setPos( const inPos : vec3 ); override;
  public { std::public }
    // CSimpleCamera::init
    procedure init( const inQuat : quat ); overload; override;
    // CSimpleCamera::init
    procedure init( const inPos, inEuler : vec3 ); overload; override;
    // CSimpleCamera::pos
    property pos : vec3 read getPos write setPos;
    // CSimpleCamera::build
    procedure build( const intype : enumCamState );
  public
    // CSimpleCamera::CSimpleCamera::doInit
    procedure doInit; override;
    // CSimpleCamera::CSimpleCamera::doDraw
    procedure doDraw; override;
    // CSimpleCamera::CSimpleCamera::doUpdate
    procedure doUpdate; override;
    // CSimpleCamera::CSimpleCamera::doFree
    procedure doFree; override;
    // CSimpleCamera::CSimpleCamera::doMessage
    procedure doMessage( var inMsg : structMsg ); override;
  end;

implementation

uses
  utils,
  os;
{ CCameraFactory }

// CSimpleCamera::doFree
procedure CCameraFactory.doFree;
begin
  inherited;
end;

// CSimpleCamera::doInit
procedure CCameraFactory.doInit;
begin
  fCurrCam := ICamera( addChild( CSimpleCamera.Create ) );
  inherited;
end;

// CSimpleCamera::getCurrCam
function CCameraFactory.getCurrCam : ICamera;
const
  errAssignCam = 'camera not assign';
begin
  exception( fCurrCam <> nil, errAssignCam );
  result := fCurrCam;
end;

// CSimpleCamera::setCurrCam
procedure CCameraFactory.setCurrCam( const inCam : ICamera );
begin
  fCurrCam := inCam;
end;

{ CSimpleCamera }

// CSimpleCamera::build
procedure CSimpleCamera.build( const intype : enumCamState );
begin
  case intype of
    // camStBuildModel
    camStBuildModel :
     begin
     modelMatrix( fMatrix[ camModelView ], _vec3( 0.0, 0.0, - 3.00 ), fQuatCurr );
     INotifier( notifier ).renderer.drawApi.setMatrix( camModelView, @fMatrix[ camModelView ] );
     end;
    // camStBuildProj
    camStBuildProj :
     begin
     frustumMatrix( fMatrix[ camProjView ], fFov, aspectRatioDefault, 0.001, 1000.0 );
     INotifier( notifier ).renderer.drawApi.setMatrix( camProjView, @fMatrix[ camProjView ] );
     end;
    // camStBuildFrustum
    camStBuildFrustum :
     ;
  end;
  // exclude state
  exclude( fState, intype );
end;

procedure CSimpleCamera.doDraw;
begin
  inherited;
end;

procedure CSimpleCamera.doFree;
begin
  // unReg matrix
  INotifier( notifier ).renderer.drawApi.unsetMatrix( camModelView, @fMatrix[ camModelView ] );
  INotifier( notifier ).renderer.drawApi.unsetMatrix( camProjView, @fMatrix[ camProjView ] );
  inherited;
end;

procedure CSimpleCamera.doInit;
begin
  init( nullvec3, nullvec3 );
  inherited;
end;

procedure CSimpleCamera.doMessage( var inMsg : structMsg );
begin
  inherited;
end;

var
  rotd : float = 0.0;

procedure CSimpleCamera.doUpdate;
var
  o : enumCamState;
  t : time;
begin
//
  include( fState, camStBuildModel );
  rotd := rotd + 0.01;
  rotate( fQuatCurr, _vec3( 0.4, 0.0, 0.1 ), rotd );
  //
  for o := low( o ) to high( o ) do
    if ( o in fState ) then
     build( o );
  //
  inherited;
end;

function CSimpleCamera.getPos : vec3;
begin
  result := ( fPosCurr );
end;

procedure CSimpleCamera.init( const inQuat : quat );
begin
  assert( false );
end;

procedure CSimpleCamera.init( const inPos, inEuler : vec3 );
begin
  fState := [ camStBuildProj, camStBuildModel ];
  fFov := fovCamDefault;
  // ident matrix
  identity( fMatrix[ camModelView ] );
  identity( fMatrix[ camProjView ] );
  // get curr quat rot
  fQuatCurr := get( fMatrix[ camModelView ] );

  rotate( fQuatCurr, _vec3( 0.4, 0.0, 0.1 ), 0.5 );

  fQuatNecessary := fQuatCurr;
end;

procedure CSimpleCamera.setPos( const inPos : vec3 );
begin
end;

end.
